import 'package:rxdart/rxdart.dart';

import '../../common/test_page.dart';

class FromCallableTestPage extends TestPage {
  FromCallableTestPage(super.title) {
    test('Rx.fromCallable.sync', () {
      var called = false;

      var stream = Rx.fromCallable(() {
        called = true;
        return 2;
      });

      expect(called);
      expect(stream);
      expect(called);
    });

    test('Rx.fromCallable.async', () {
      var called = false;

      var stream = FromCallableStream(() async {
        called = true;
        await Future<void>.delayed(const Duration(milliseconds: 10));
        return 2;
      });

      expect(called);
      expect(stream);
      expect(called);
    });

    test('Rx.fromCallable.reusable', () {
      var stream = Rx.fromCallable(() => 2, reusable: true);
      expect(stream.isBroadcast);

      stream.listen(null);
      stream.listen(null);

      expect(true);
    });

    test('Rx.fromCallable.singleSubscription', () {
      {
        var stream = Rx.fromCallable(() =>
            Future.delayed(const Duration(milliseconds: 10), () => 'Value'));

        expect(stream.isBroadcast);
        stream.listen(null);
        expect(() => stream.listen(null));
      }

      {
        var stream = Rx.fromCallable(() => Future<String>.error(Exception()));

        expect(stream.isBroadcast);
        stream.listen(null, onError: (Object e) {});
        expect(
                () => stream.listen(null, onError: (Object e) {}));
      }
    });

    test('Rx.fromCallable.asBroadcastStream', () async {
      final stream = Rx.fromCallable(() => 2).asBroadcastStream();

      stream.listen(null);
      stream.listen(null);

      expect(stream.isBroadcast);
    });

    test('Rx.fromCallable.sync.shouldThrow', () {
      var stream = Rx.fromCallable<String>(() => throw Exception());

      expect(stream);
    });

    test('Rx.fromCallable.async.shouldThrow', () {
      {
        var stream = Rx.fromCallable<String>(() async => throw Exception());

        expect(stream);
      }

      {
        var stream = Rx.fromCallable<String>(() => Future.error(Exception()));

        expect(stream);
      }
    });

    test('Rx.fromCallable.sync.pause.resume', () {
      var stream = Rx.fromCallable(() => 'Value');

      stream.listen((v) => expect(v) as void Function(String event)?,
      )
          .pause(Future<void>.delayed(const Duration(milliseconds: 50)));
    });

    test('Rx.fromCallable.async.pause.resume', () {
      var stream = Rx.fromCallable(() async {
        await Future<void>.delayed(const Duration(milliseconds: 10));
        return 'Value';
      });

      stream.listen((v) => expect(v) as void Function(String event)?,
      )
          .pause(Future<void>.delayed(const Duration(milliseconds: 50)));
    });
  }

}